////////////////////////////////////////////////////////////////////////////////
//(c) Intelliquip, Inc. 2001
////////////////////////////////////////////////////////////////////////////////
//$Log:
// 13   Version 10.0 (Current View)1.12        5/2/2011 11:50:19 AM   Jeff
//      Heigl      IDD#09523: mobile app infrastructure
// 12   Version 10.0 (Current View)1.11        3/17/2011 9:20:10 AM   Hai Hoang
//            IDD#09537: Implemented xsl caching for mainOptionSelection page.
//      Sharing Template caching code.
// 11   Version 10.0 (Current View)1.10        3/1/2011 10:03:16 AM   Stephen
//      Kish    IDD#08949: Refactoring appRootURL to either user or server
// 10   Version 10.0 (Current View)1.9         1/28/2011 12:03:46 PM  Jeff
//      Heigl      IDD#09403: debug support
// 9    Version 10.0 (Current View)1.8         1/21/2011 5:40:03 PM   Hai Hoang
//            IDD#09401: fixed xsl template caching problem
// 8    Version 10.0 (Current View)1.7         11/13/2009 10:16:42 AM Jeff
//      Heigl      IDD#8193: reject reasons page cleanup
// 7    Version 10.0 (Current View)1.6         10/20/2009 11:56:33 AM Jeff
//      Heigl      IDD#8193: gas constituents dropdowns
// 6    Version 10.0 (Current View)1.5         10/20/2009 10:07:09 AM Jeff
//      Heigl      IDD#8193: gas constituents page impl
// 5    Version 10.0 (Current View)1.4         10/19/2009 5:52:46 PM  Jeff
//      Heigl      IDD#8193: gas constituents normalize button
// 4    Version 10.0 (Current View)1.3         9/24/2009 2:24:49 PM   Jeff
//      Heigl      IDD#8163: compressor curve unit tests, xaml html file now
//      has a better message
// 3    Version 10.0 (Current View)1.2         9/23/2009 5:03:25 PM   Jeff
//      Heigl      IDD#8162: transport log timings added, curve chartable and
//      director cache implemented
// 2    Version 10.0 (Current View)1.1         6/22/2009 12:05:23 PM  Jeff
//      Heigl      IDD#7911: compressor cos page and common xml impl
// 1    Version 10.0 (Current View)1.0         6/19/2009 4:57:13 PM   Jeff
//      Heigl      
//$
//$NoKeywords$
////////////////////////////////////////////////////////////////////////////////
package com.intelliquip.hydraulicselection.control.web;

import static com.intelliquip.hydraulicselection.SelectorProperties.getServerAppRootURL;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.transform.Templates;

import com.intelliquip.core.Language;
import com.intelliquip.core.TransportLogBean;
import com.intelliquip.core.TransportLogWrapper;
import com.intelliquip.core.xml.XMLDocHTMLTransformer;
import com.intelliquip.core.xml.XMLDocument;
import com.intelliquip.core.xml.XmlDocHTMLMobileTransformer;
import com.intelliquip.hydraulicselection.xml.AbstractSelectorPage;
import com.intelliquip.hydraulicselection.xml.SelectorTemplatesManager;
import com.intelliquip.util.IOUtils;
import com.intelliquip.util.ServletUtils;
import com.intelliquip.util.XMLUtils;

public class SelectorResponseGenerator {

	private static final boolean WRITE_XML_TO_FILE_FOR_DEBUG = false;

	private final HttpServletRequest request;
	private final HttpServletResponse response;
	private final AbstractSelectorPage page;
	private final PageDetails pageDetails;


	public SelectorResponseGenerator(HttpServletRequest request, HttpServletResponse response, AbstractSelectorPage page) {
		this.request = request;
		this.response = response;
		this.page = page;
		this.pageDetails = page.getPageDetails();
	}

	public void generateResponse(TransportLogWrapper tLog) throws Exception {
		XMLDocument xmlDoc = writeXmlDocument(tLog);
		writeToResponse(xmlDoc, tLog);
	}

	private XMLDocument writeXmlDocument(TransportLogWrapper tLog) throws Exception {
		XMLDocument doc = new XMLDocument();
		doc.appendChild(page.writeXmlElement(doc, tLog));
		if(WRITE_XML_TO_FILE_FOR_DEBUG) {
			XMLUtils.writeToTempFileForDebug(page.getPageDetails().getXslFileName(), doc);
		}
		return doc;
	}

	public void writeToResponse(XMLDocument xmlDoc, TransportLogWrapper tLog) throws Exception, IOException {
		TransportLogWrapper tLog_writeToResponse = TransportLogWrapper.build(tLog, "writeToResponse");
		TransportLogBean.createDeltaEntry(tLog_writeToResponse);

		String xslApp = page.getUserPreferences().getXSLFolder(pageDetails.getXslFileName());
		String xslRelativePath = xslApp + "xsl/" + pageDetails.getXslFileName();
		URL xslUrl = getXslUrl(xslRelativePath);

		if (page.useXslTemplateCache()) {
			writeToResponseUsingTemplates(xslRelativePath, xslUrl, xmlDoc, tLog_writeToResponse);
		} else {
			writeToResponseUsingXslStream(xmlDoc, xslUrl, tLog_writeToResponse);
		}

		TransportLogBean.setDeltaEndTime(tLog_writeToResponse);
	}

	private void writeToResponseUsingTemplates(String xslRelativePath, URL xslUrl, XMLDocument xmlDoc, TransportLogWrapper tLog) throws Exception {
		TransportLogWrapper tLog_writeToResponse = TransportLogWrapper.build(tLog, "writeToResponseUsingTemplates");
		TransportLogBean.createDeltaEntry(tLog_writeToResponse);

		Templates templates = getTemplates(xslRelativePath, xslUrl, tLog);
		transformUsingTemplates(xmlDoc, templates, tLog);

		TransportLogBean.setDeltaEndTime(tLog_writeToResponse);
	}

	private Templates getTemplates(String xslRelativePath, URL xslUrl, TransportLogWrapper tLog) throws Exception {
		TransportLogBean.createDeltaEntry(tLog, "getTemplates");

		Templates templates = SelectorTemplatesManager.get(xslRelativePath);
		if (templates == null) {
			templates = createTemplates(xslUrl);
			SelectorTemplatesManager.put(xslRelativePath, templates);
		}

		TransportLogBean.setDeltaEndTime(tLog, "getTemplates");

		return templates;
	}

	private URL getXslUrl(String xslRelativePath) throws MalformedURLException {
		StringBuffer xslPath = new StringBuffer();
		xslPath.append(ServletUtils.getScheme_ServerName_Port(request));
		xslPath.append(request.getContextPath());
		xslPath.append("/");
		xslPath.append(xslRelativePath);
		URL xslURL = new URL(xslPath.toString());
		return xslURL;
	}

	private Templates createTemplates(URL xslUrl) throws Exception {
		Templates templates;
		InputStream xslIn = null;
		try {
			xslIn = xslUrl.openStream();
			templates = XMLDocument.createTemplates(xslIn, getServerAppRootURL());
		} finally {
			IOUtils.closeInputStream(xslIn);
		}
		return templates;
	}


	private void transformUsingTemplates(XMLDocument xmlDoc, Templates templates, TransportLogWrapper tLog) throws IOException {
		TransportLogBean.createDeltaEntry(tLog, "transformUsingTemplates");

		XMLDocHTMLTransformer htmlTransform;
		if(DisplayController.isMobileDevice(request)) {
			htmlTransform = new XmlDocHTMLMobileTransformer(xmlDoc, getLanguage(), response.getWriter(), templates, getServerAppRootURL());
		} else {
			htmlTransform = new XMLDocHTMLTransformer(xmlDoc, getLanguage(), response.getWriter(), templates, getServerAppRootURL());
		}


		htmlTransform.addParams(page.getTransformParameters());
		htmlTransform.transformAndWriteHTML();

		TransportLogBean.setDeltaEndTime(tLog, "transformUsingTemplates");
	}

	private Language getLanguage() {
		return page.getUserPreferences().getLanguage();
	}

	private void writeToResponseUsingXslStream(XMLDocument doc, URL xslUrl, TransportLogWrapper tLog) throws Exception, IOException {
		TransportLogBean.createDeltaEntry(tLog, "writeToResponseUsingXslStream");

		InputStream xslStream = null;
		try {
			// retrieve input stream for XSL, currently customDataXSLs cannot use Templates
			xslStream = xslUrl.openStream();

			XMLDocHTMLTransformer htmlTransform;
			if(DisplayController.isMobileDevice(request)) {
				htmlTransform = new XmlDocHTMLMobileTransformer(doc, getLanguage(), response.getWriter(), xslStream, getServerAppRootURL());
			} else {
				htmlTransform = new XMLDocHTMLTransformer(doc, getLanguage(), response.getWriter(), xslStream, getServerAppRootURL());
			}

			htmlTransform.addParams(page.getTransformParameters());
			htmlTransform.transformAndWriteHTML();
		} finally {
			IOUtils.closeInputStream(xslStream);
		}

		TransportLogBean.setDeltaEndTime(tLog, "writeToResponseUsingXslStream");
	}

}
